
var XML_CLM={
  ERR_NO   :0,
  ERR_DEP  :1,
  ERR_EQ   :2,
  ERR_VAL  :3,
  ERR_BHINT:4,
  ERR_EQGRP:5,
  ERR_GRPEQ:6,
  ERR_BADY :7,
  ERR_BAD  :8,  // bad value 
  
  _usesame:0,
  _usegroup:0,
  _alreadyasked:0
};

//--------------------------------------------------------------------------- 
// Claim xml data structure
//---------------------------------------------------------------------------

function CreateClaim(cl) {
  var child,subchild,val;
  var claim= XMLDOMDOS.createElement("claim");
  
  //claims.appendChild(XMLROOT.createTextNode("\t"));
  
  // number of claim
  attr = XMLDOMDOS.createAttribute("clnum");
  attr.value = cl;
  claim.setAttributeNode(attr);
  
  // final value = N not novel, I, not inventive, ? not decided, * new and inventive
  attr = XMLDOMDOS.createAttribute("val");
  attr.value = "??";
  claim.setAttributeNode(attr);
    
  //claim.appendChild(XMLROOT.createTextNode("\n\t\t"));
  
  // add dep
  attr = XMLDOMDOS.createAttribute("dep");
  attr.value = "";
  claim.setAttributeNode(attr);
  
  // add eq
  attr = XMLDOMDOS.createAttribute("eq");
  attr.value = "";
  claim.setAttributeNode(attr);

 // add import info (only meaningfull for claimsets after 1) 
  attr = XMLDOMDOS.createAttribute("I");
  attr.value = "";
  claim.setAttributeNode(attr);
  
  // add group
  attr = XMLDOMDOS.createAttribute("G");
  attr.value = "";
  claim.setAttributeNode(attr);
  
  // add clarity 
  attr = XMLDOMDOS.createAttribute("C");
  attr.value = "C";
  claim.setAttributeNode(attr);
  
  // add X doc 
  attr = XMLDOMDOS.createAttribute("X");
  attr.value = "";
  claim.setAttributeNode(attr);
  
  // add Y doc  
  attr = XMLDOMDOS.createAttribute("Y");
  attr.value = "";
  claim.setAttributeNode(attr);
  
  // add A doc  
  attr = XMLDOMDOS.createAttribute("A");
  attr.value = "";
  claim.setAttributeNode(attr);
  
  // add B doc  
  attr = XMLDOMDOS.createAttribute("B");
  attr.value = "";
  claim.setAttributeNode(attr);

  
  // other X,Y,A,B docs 
  child = XMLDOMDOS.createElement("clsdocs");
  claim.appendChild(child);

  // other X,Y,A,B docs 
  child = XMLDOMDOS.createElement("clarobjs");
  claim.appendChild(child);

  // add features[]
  child = XMLDOMDOS.createElement("features");
  // add 1 feature (whole claim)
  child.appendChild(CreateFeature(cl,""));  
  claim.appendChild(child);


  //alert("Added feature for "+cl); 
  return claim;
}

XML_CLM._addfeatureelem=function(cl) {
  // add features[]
  var child = XMLDOMDOS.createElement("features");
  // add 1 feature (whole claim)
  child.appendChild(CreateFeature(cl,""));  
  CLAIMS[cl-1].appendChild(child);
  return child;
}

XML_CLM._addclsdocseelem=function(cl) {
  // add other docs[]
  var child = XMLDOMDOS.createElement("clsdocs");
  CLAIMS[cl-1].appendChild(child);
  return child;
}

XML_CLM._addclarobjselem=function(cl) {
  // add features[]
  var child = XMLDOMDOS.createElement("clarobjs");
  // add 1 feature (whole claim)
  CLAIMS[cl-1].appendChild(child);
  return child;
}




//---------------------------------------------------------------------------
// Storage for claim text (without features)
//---------------------------------------------------------------------------
         
function SetClaimVerbatim(cl,v) {
  CLAIMS[cl-1].selectSingleNode("features").setAttribute("verbatim",v);
}

function GetClaimVerbatim(cl) {
  return CLAIMS[cl-1].selectSingleNode("features").getAttribute("verbatim")|| "";
}

function SetClaimHeader(cl,h) {
  CLAIMS[cl-1].selectSingleNode("features").setAttribute("head",h);
}

function GetClaimHeader(cl) {
  return CLAIMS[cl-1].selectSingleNode("features").getAttribute("head") || "";
}



//---------------------------------------------------------------------------
// Claim Dependencies
//---------------------------------------------------------------------------

function GetClaimDep(cl) {
  return CLAIMS[cl-1].getAttribute("dep");
}

function SetClaimDep(cl,val) {
  if(dep_isindependent(val)) {
    val=val.toUpperCase();
     SetClaimCategory(cl,val);
  } else if(cl<=val) {
    alert("Cannot change dependency of claim "+cl+" to "+val+" because circular deps are not allowed");
    return false;
  } else if(val && !is_claim(val)) {
    alert("Cannot change dependency of claim "+cl+" to "+val+" because claim "+val+" does not exist");
    return false;
  } else {
    SetClaimCategory(cl,GetClaimCategory(val));
  }
  CLAIMS[cl-1].setAttribute("dep",val);   
  return true;
}

// obsolete
function is_clindependent(cl) {
  var _dep=GetClaimDep(cl)||""; 
  return !parseInt(_dep) || (GetGroupsLength()>1 && (GetClaimGroup(_dep) != GetClaimGroup(cl)));
}

// obsolete
function is_cldependent(cl) {
  var _dep=GetClaimDep(cl)||"";
  if(parseInt(_dep) && GetClaimGroup(_dep) == GetClaimGroup(cl)) return _dep;
  return "";
}


function dep_isindependent(d) { 
  return d && !parseInt(d);
}

function dep_isdependent(d) {
  return d && parseInt(d);
}

function claim_isindependent(cl) {
  return dep_isindependent(GetClaimDep(cl));
}

function claim_isdependent(cl) {
  return dep_isdependent(GetClaimDep(cl));
}

function claim_isgrpindependent(cl) {
  var _dep=GetClaimDep(cl); 
  return dep_isindependent(_dep) || (GetGroupsLength()>1 && (GetClaimGroup(_dep) != GetClaimGroup(cl)));
}

function claim_isgrpdependent(cl) {
  var _dep=GetClaimDep(cl); 
  return dep_isdependent(_dep) && (GetGroupsLength()<=1 || (GetClaimGroup(_dep) == GetClaimGroup(cl)));
}

//---------------------------------------------------------------------------
// Claim value. Not new, not inventive, etc... 
// Claim Value = { Xn, XI, A , ??}
//---------------------------------------------------------------------------

function GetClaimValue(cl) {
  return CLAIMS[cl-1].getAttribute("val");
}

function SetClaimValue(cl,val) {
  //alert("Set claim "+cl+"to "+val);
  if(CLAIMS[cl-1].getAttribute("val") !=val) {
    set_Tainted(cl);
  }
  CLAIMS[cl-1].setAttribute("val",val||"");
}

function IsClaimNotNovel(cl) {
  return GetClaimValue(cl)=="XN"; // not new ?
}
function SetClaimNotNovel(cl) { 
  SetClaimValue(cl,"XN");
}

function SetClaimNotInventive(cl) { 
  SetClaimValue(cl,"XI");
}
function IsClaimNotInventive(cl) {
  return GetClaimValue(cl)=="XI"; 
}

function IsClaimNovelandInventive(cl) {
  return GetClaimValue(cl)=="A"; // not new ?
}
function SetClaimNovelandInventive(cl) { 
  SetClaimValue(cl,"A");
}

function IsClaimSearched(cl) {
  return GetClaimDoc_X(cl) || GetClaimDoc_Y(cl) || GetClaimDoc_A(cl) || GetClaimDoc_B(cl); 
}

function SetClaimNotSearched(cl) {
  _SetClaimDoc_d(cl,"X","");
  _SetClaimDoc_d(cl,"Y","");
  _SetClaimDoc_d(cl,"A","");
  _SetClaimDoc_d(cl,"B","");
  _SetClaimDoc_d(cl,"C","");
  return SetClaimValue(cl,"??"); 
}

//---------------------------------------------------------------------------
// Categories are defined in data/keywords.xml 
//---------------------------------------------------------------------------

function SetClaimCategory(cl,cat) { 
  //alert(cl+" "+cat);
  CLAIMS[cl-1].setAttribute("cat",cat);
   //alert("done");
}

function GetClaimCategory(cl) {
  return CLAIMS[cl-1].getAttribute("cat") || "";
}

function propagate_categories(cl) {
  var cl_iter=new claim_iterator(cl);
  while(!cl_iter.end()) {
    if(dep_isdependent(cl_iter.getValue())) {
      SetClaimCategory(cl_iter.getValue(),GetClaimCategory(GetRootClaim(cl_iter.getValue())));     
    }
    cl_iter.next();
  }
}

//---------------------------------------------------------------------------
// Claim Group
// Groups are { I, II, III, IV, ....}
//---------------------------------------------------------------------------

// Cannot set different groups for eq claims 
function SetClaimGroup(cl,G) {
  if(G) {
    var eq=GetClaimEq(cl);
    if(eq && GetClaimGroup(eq) != G) {
      alert("Cannot set group "+G+" to claim "+cl+" because claim "+cl+" is eq to claim "+eq+" in group "+GetClaimGroup(eq));
      return XML_CLM.ERR_EQGRP;
    } 
    var eq_iter=Eq_claim_iterator(cl);
    while(!eq_iter.end()) {
      var eqgrp=GetClaimGroup(eq_iter.getValue());
      if(eqgrp != G) {	
	SetClaimGroupWarn(eq_iter.getValue(),"Should belong to group "+G);		 
      } else {
	SetClaimGroupWarn(eq_iter.getValue(),"");
      }		 
      eq_iter.next();
    }
  }
  SetClaimGroupWarn(cl,""); 
  CLAIMS[cl-1].setAttribute("G",(G||""));
  return XML_CLM.ERR_NO;
}


function GetClaimGroup(cl) { 
  return CLAIMS[cl-1].getAttribute("G")||"";
}


//---------------------------------------------------------------------------
// Global claim clarity flag 
//---------------------------------------------------------------------------

function GetClaimClarity(cl) {
  //assert("!"+(eq || 0));
  return CLAIMS[cl-1].getAttribute("C");
}

function SetClaimClarity(cl,val) {
  CLAIMS[cl-1].setAttribute("C",val);
}

function IsClaimUnclear(cl,eq) { 
  return GetClaimClarity(cl,eq) && GetClaimClarity(cl,eq) !="C";
}

function IsClaimClear(cl,eq) {
  return !GetClaimClarity(cl,eq) || GetClaimClarity(cl,eq)=="C";
}

function SetClaimUnclear(cl) {
  SetClaimClarity(cl,"U"); 
}

function SetClaimClear(cl) {
  SetClaimClarity(cl,""); 
}


//---------------------------------------------------------------------------
// Claim wide clarity objections, can be more than one
// See features.xml for expression wide clarity objections 
//---------------------------------------------------------------------------

function GetClaimClarityObjs(cl) {
  var clobjs=CLAIMS[cl-1].selectSingleNode("clarobjs");
  if(!clobjs) {
    return XML_CLM._addclarobjselem(cl);
  }
  return clobjs;
}

function GetClaimClarityObj(cl,objtype) {
 var clobjs=GetClaimClarityObjs(cl);
 var clobj=clobjs.selectSingleNode("clarobj[ @type='"+objtype+"']");
 if(!clobj) {
   return "";
 }
 return clobj.getAttribute("val");
}


// Clarity objections can be deducted or explictly stated/removed by use.
function AddClaimClarityObj(cl,objtype,param,opt) {
  var clobjs=GetClaimClarityObjs(cl);
  var clobj=clobjs.selectSingleNode("clarobj[ @type='"+objtype+"']");
  if(!clobj) {
    clobj=XMLDOMDOS.createElement("clarobj");
    clobjs.appendChild(clobj);
  }
  if(!opt || opt=="user" || (opt=="auto" && clobj.getAttribute("by") != "user")) {
    clobj.setAttribute("by", opt || "user");
    clobj.setAttribute("type",objtype);
    clobj.setAttribute("val",param || "");
    clobj.setAttribute("active","yes");   
  }
  if(GetClaimClarityObjs(cl).selectNodes("clarobj[ @active != \"no\"]").length!=0) {
    SetClaimUnclear(cl);
  }  
}

function RemoveClaimClarityObj(cl,objtype,opt) {
  var clobjs=GetClaimClarityObjs(cl);
  var clobj=clobjs.selectSingleNode("clarobj[ @type='"+objtype+"']");
  if(clobj && (!opt || opt=="user" || (opt=="auto" && clobj.getAttribute("by") != "user"))) {
    clobj.setAttribute("active","no");       
    //clobjs.removeChild(clobj);
  }
  // update clarity from features
  if(GetClaimClarityObjs(cl).selectNodes("clarobj[ @active != \"no\"]").length==0) {
    featureupdateclarity(cl);
  }
}

function claimclarity_iterator(cl) {
  this.base= array_iterator;
  this.base(GetClaimClarityObjs(cl).selectNodes("clarobj[ @active != \"no\"]"));
}

claimclarity_iterator.prototype=new array_iterator;
claimclarity_iterator.prototype.constructor=claimclarity_iterator;
claimclarity_iterator.prototype.getType=function() { return this.getElem().getAttribute("type")};
claimclarity_iterator.prototype.getParam=function() { return this.getElem().getAttribute("val")};


//---------------------------------------------------------------------------
// Claim equivalence 
// Claim Eq: if 1) EQ(cl1) == cl2 iff EQ(cl2) == ""  and
//              2) EQ(cl1) == cl2 iff cl1 is dependent or cl2 is independent and
//              3) EQ(cl1) == cl2 iff cl2 < cl1 or (cl2 is independent and cl1 is dependent)
// Rules:
// 1) no chained eqs 
// 2) force independent claims first, so all features of independent claims are specified
// 3) avoid circular dependencies through equivalences 
//---------------------------------------------------------------------------

function GetClaimEq(cl) {
  return CLAIMS[cl-1].getAttribute("eq");
}

function SetClaimEq(cl,val) {
  var dep=GetClaimDep(cl);

  if(val) {
    if(!is_claim(val)) {
      alert("Cannot set claim "+cl+" equal to  claim "+val+" because claim "+val+" does not exist");
      return XML_CLM.ERR_BAD;
    }    
    if(GetClaimEq(val)) {
      alert("Cannot set claim "+cl+" equivalent to claim "+val+" because the later is equivalent to "+GetClaimEq(val)+".");
      return XML_CLM.ERR_BAD;
    }
    if(is_clindependent(cl) && is_cldependent(val)) {
      alert("An independent claim ("+cl+") cannot be set equivalent to a dependent claim ("+val+").");
      return XML_CLM.ERR_BAD;
    }   
    if(cl < val) {
      if(is_cldependent(val)) {
	alert("A claim ("+cl+") cannot be set equivalent to a higher dependent claim ("+val+").");
	return XML_CLM.ERR_BAD;
      }
      if(is_cldindependent(cl)) {
	alert("An independent claim ("+cl+") cannot be set equivalent to a higher independent claim ("+val+").");
	return XML_CLM.ERR_BAD;
      }
    }

    if(is_cldependent(cl)) {
      if(GetClaimDoc_X(dep) && GetClaimDoc_X(val) && 
	 GetClaimDoc_X(dep) != GetClaimDoc_X(val))  {
	if(GetClaimEq(cl)==val) {
	  SetClaimEqWarn(cl,"Incompatible equality"); // refreshing (?)
	} else {
	  alert("Incompatible equality");
	}
	return XML_CLM.ERR_EQ;
      }
    }
  }
  SetClaimEqWarn(cl,"");
  CLAIMS[cl-1].setAttribute("eq",(val||""));
  return XML_CLM.ERR_NO;
}


//------------------------------------------------------------------------------
// Claim Diff. 
// Use claim number diff as claim to be compared to, defaults to cl
//------------------------------------------------------------------------------

function GetClaimDiff(cl) {
  return CLAIMS[cl-1].getAttribute("diff") || cl;
}

function SetClaimDiff(cl,val) {
  CLAIMS[cl-1].setAttribute("diff",(val||""));
}

function SetRefDiff(ver) {
  CLAIMSET.setAttribute("diff",(ver||""));
}

function GetRefDiff(ver) {
  return CLAIMSET.getAttribute("diff") || 1;
}

//---------------------------------------------------------------------------
// Cross claimsets claim access methods
//---------------------------------------------------------------------------

function GetClaimNodeFromVers(cl,vers) {
  return CLAIMSETS[vers-1].selectSingleNode("claims").childNodes[cl-1];
}

function GetClaimAttrFromVers(cl,vers,attr) {
  return  GetClaimNodeFromVers(cl,vers).getAttribute(attr);
}

//---------------------------------------------------------------------------
// Handle importing opinions from previous claimset versions 
// politics: no dereference, copy on import
// not copied: dependence 
//---------------------------------------------------------------------------

function GetClaimImport(cl) {
  return CLAIMS[cl-1].getAttribute("I") || "";
}

function SetClaimImport(cl,val) {
  CLAIMS[cl-1].setAttribute("I",val||"");
}

function GetClaimImpEq(cl) {
  return CLAIMS[cl-1].getAttribute("IEQ") || "";
}

function SetClaimImpEq(cl,val) {
  CLAIMS[cl-1].setAttribute("IEQ",val||"");
}


//---------------------------------------------------------------------------
// Replace claim with another claim , full import 
//---------------------------------------------------------------------------    
	
function ReplaceClaim(cl,vers,icl,ivers) {
  var newnode;
  var dep=GetClaimDep(cl);
  var imp=GetClaimImport(cl);
  var diff= GetClaimDiff(cl);
  var verb=GetClaimVerbatim(cl);

  if(icl && ivers) { // non empty import
    var fromnode=GetClaimNodeFromVers(icl,ivers);
    if(fromnode) {
      newnode=fromnode.cloneNode(true);
      newnode.setAttribute("clnum",cl);
    } else {
      alert("No claim set version "+ vers +"found");
      return 0;
    }      
    CLAIMSET.selectSingleNode("claims").replaceChild(newnode,CLAIMS[cl-1]);
 
    claim_import_group(cl,icl,ivers);
   
    // info that should be kept from original claim
    SetClaimVerbatim(cl,verb);
    SetClaimDep(cl,dep);
    SetClaimImport(cl,imp);
    SetClaimDiff(cl,diff);  
    import_fixeqs(cl,icl,ivers,GetClaimAttrFromVers(icl,ivers,"eq"));

    // check features of new imported claim
    var tf_iter= new claim_features_iterator(cl);
    while(!tf_iter.end()) {          
      // Mark all features as imported
      tf_iter.setImp(ivers+"/"+icl+"."+tf_iter.gettf());
      tf_iter.next();
    }
    import_fixtfeqs(cl,icl,ivers);
  } else { // replace previous node with a blank one
    CLAIMSET.selectSingleNode("claims").replaceChild(CreateClaim(cl),CLAIMS[cl-1]);
    // copy previous values
    SetClaimDep(cl,dep);
    SetClaimImport(cl,imp);
    SetClaimDiff(cl,diff);
    SetClaimVerbatim(cl,verb);
    SetFeatureDesc(cl,1,GetClaimVerbatim(cl));
  } 
  return true;
}


//---------------------------------------------------------------------------
// Document values for claim
// DocVal is { XN, XI, Y, A }
// UsrDocVal is taken from strategy therefore UsrDocVal is { X, Y, A, "" }
// AutoDocVal is computed from passages/hints AutoDocVal is { XN, XI, Y, ""} 
//---------------------------------------------------------------------------

function Strat_toVal(strat) {
  switch(strat) {
  case "X":
    return GetClaimDocUsrAttr(cl,pn,"val");
  case "B":
  case "C":
    return "A";
  }
  return strat;
}

// retreive node , create if not found 
function GetDocValNode(cl,pn,opt) {
  var clsdocs=GetClaimDocs(cl);
  if(!clsdocs) {
    clsdocs=XML_CLM._addclsdocseelem(cl);
  }  
  var nodedoc=clsdocs.selectSingleNode("cldoc [ @docid = \""+pn+"\"]");  
  if(!nodedoc && pn) { // create node if document not empty
    nodedoc=XMLDOMDOS.createElement("cldoc");
    nodedoc.setAttribute("docid",pn);
    clsdocs.appendChild(nodedoc);
  }
  return nodedoc;
}  

//
// User set value 
// values are : X, Y, A, ""

function GetClaimDocUsrVal(cl,pn) {
  return GetDocValNode(cl,pn).getAttribute("val");
}

function GetClaimDocUsrAttr(cl,pn,attr) {
  return GetDocValNode(cl,pn).getAttribute(attr);
}

function SetClaimDocUsrVal(cl,pn,val) {
  if(GetClaimEq(cl)) {
    //alert("Trying to change doc val for claim "+cl+" equal to "+GetClaimEq(cl));
    return;
  }
  GetDocValNode(cl,pn).setAttribute("val",val||"");
}

//
// Computed value
// values are : XN, XI, or ""

function GetClaimDocAutoVal(cl,pn) {
  return GetDocValNode(cl,pn).getAttribute("autoval");
}
  
function SetClaimDocAutoVal(cl,pn,val) {
  if(GetClaimEq(cl)) {
    //alert("Trying to change doc val for claim "+cl+" equal to "+GetClaimEq(cl));
    return;
  }
  GetDocValNode(cl,pn).setAttribute("autoval",val||"");
}

// Val value has been set by user
function IsClaimDocValUser(cl,pn) {
  return GetClaimDocUsrVal(cl,pn);
}

// Val value is computed
function IsClaimDocValAuto(cl,pn) {
  return GetClaimDocAutoVal(cl,pn);
}


// just write doc value for document docid, no checking  
function SetClaimDocVal(cl,pn,val) {
  SetClaimDocUsrVal(cl,pn,val);
}

// if usrval exists, some strategy exists for pn
function  usrval_toval(cl,pn,usrval) {    
  switch(usrval) {
  case "X":
    return GetClaimDocUsrAttr(cl,pn,"val");
  default:
    return usrval;
  }
}

//
// ClaimDocVal is computed on access, from usrval and autoval
// 

function GetClaimDocVal(cl,pn,eq,dep) { 
  var eq=eq || GetClaimEq(cl);
  var dep=dep || GetClaimDep(cl);
  var usrval=GetClaimDocUsrVal(cl,pn),depval="";

  // Dependent claim, eq irrelevant 
  if(claim_isgrpdependent(cl)) {
    depval=GetClaimDocVal(dep,pn);
    //alert("GetClaimDocVal: dependent claim "+cl+ " depends on "+dep+" with value "+depval);
    if(!depval && (usrval=="X")) { 
      // no value for parent, no X value for child   
      // alert("cannot be X and parent has no value");
      return "";     
    }
    if(depval=="A" && usrval) { // downgrade
      return "A";
    }
  }
  
  // Try eq first
  if(eq) { // equal claim must take 
    //alert("GetClaimDocVal: EQ "+cl+"("+pn+") is "+_eq); 
    var eqautoval=GetClaimDocAutoVal(eq,pn);
    switch(eqautoval) {
    case "XN":
    case "XI":
      if(claim_isgrpindependent(cl)) { // independent claim is always equal   
	return eqautoval;
      }
      // dependent claim 
      if(depval=="XN") { // this value is only possible if depval is X or greater
	return eqautoval ;
      }
      if(depval=="XI") {
	return "XI";
      }
      return depval || "A"; // any value below X is allowed 
    case "A":
      return "A";
    case "Y":
      if(claim_isgrpindependent(cl) || depval!="A") { // independent claim is always equal   
	return "Y";
      }
    default: // no autoeqval, no upgrade possible
      var eqval=GetClaimDocVal(eq,pn,GetClaimEq(eq));
      if(claim_isgrpindependent(cl)) { // independent claim is always equal   
	return eqval;	 
      } else {                  // dependent claim must take into account upper claim
	//alert("GetClaimDocVal: eq indep default min ("+_depval+" , "+eqval+")");
	return (catcmp(eqval,depval)==">") ? depval : eqval;
      }
    } 
  } 
  // not eq 
  var autoval=GetClaimDocAutoVal(cl,pn);
  //alert("GetClaimDocVal: NEQ "+cl+"("+pn+")-> auto: "+autoval+" usr: "+usrval); 
  switch(autoval) {
  case "XN":
  case "XI":
    if(claim_isgrpindependent(cl)) { // independent claim 
      return autoval;
    }
    // dependent claim 
    if(depval=="XN") { // this value is only possible if depval is X or greater
      return autoval ;
    }
    if(depval=="XI") {
      return "XI";
    }
    return depval || "A"; // any value below X is allowed 
  case "Y":
    if(claim_isgrpindependent(cl) || depval!="A") { // independent claim 
      return "Y";
    }
  case "A":
    //alert("Autoval is A");
    return "A";
  default: // no autoval
    //alert("GetClaimDocVal: default min ("+_depval+" , "+usrval+")");
    if(claim_isgrpindependent(cl)) {
      return usrval_toval(cl,pn,usrval);
    }
    return (valcmp(usrval_toval(cl,pn,usrval),depval)==">") ? depval : usrval_toval(cl,pn,usrval);
  }
}


// Trimaran-style document value is used for each document from the strategy 
// used for backwards compat
// 
function ClaimValueToClaimDocValue(val){
  switch(val) {
  case "-N":
    return "XN";
  case "-I":
    return "XI";
  case "++":
    return "A";
  default:
    return val;
  }
}

//---------------------------------------------------------------------------
// 
//  Document local (stored)  strategy 
//  Strategy is X, Y, A, B, C, H, val
//  Stored   is X, y, A1, A2, A3, H, val
//---------------------------------------------------------------------------

function claimstrat_tolocalstrat(newcat) {
  switch(newcat) {
  case "A":
    return "A1";
  case "B":
    return "A2";
  case "C":
    return "A3";
  }
  return newcat;
}


function DumpClaimDocStrat(cl,pn) {
  var nodedoc=GetDocValNode(cl,pn);
  return "X="+nodedoc.getAttribute("X")+", A="+nodedoc.getAttribute("A1")+" H="+nodedoc.getAttribute("H");
}


function PushClaimDocStrat(cl,pn) {
  if(pn) {
    if(GetClaimEq(cl)) {
      //alert("Trying to change doc val for claim "+cl+" equal to "+GetClaimEq(cl));
      return;
    }
    var nodedoc=GetDocValNode(cl,pn);
    nodedoc.setAttribute("X",GetClaimDoc_X(cl));
    nodedoc.setAttribute("Y",GetClaimDoc_Y(cl));
    nodedoc.setAttribute("A1",GetClaimDoc_A(cl));
    nodedoc.setAttribute("A2",GetClaimDoc_B(cl));
    nodedoc.setAttribute("A3",GetClaimDoc_C(cl));
    nodedoc.setAttribute("H",GetClaimHint(cl));
    nodedoc.setAttribute("val",GetClaimValue(cl));
  }
  //alert("Pushed "+pn+" "+DumpClaimDocStrat(cl,pn));
}

// store strat value for document 
function PushClaimDocVal(cl,pn,attr,val) {
  if(!attr || !pn || GetClaimEq(cl)) {
    return;
  }
  GetDocValNode(cl,pn).setAttribute(attr,val||"");  
}

// Restore stored strategy
function PopClaimDocStrat(cl,pn) {
  if(pn) {
    var nodedoc=GetDocValNode(cl,pn);
    CLAIMS[cl-1].setAttribute("X",nodedoc.getAttribute("X")||"");
    CLAIMS[cl-1].setAttribute("Y",nodedoc.getAttribute("Y")||"");
    CLAIMS[cl-1].setAttribute("A",nodedoc.getAttribute("A1")||"");
    CLAIMS[cl-1].setAttribute("B",nodedoc.getAttribute("A2")||"");
    CLAIMS[cl-1].setAttribute("C",nodedoc.getAttribute("A3")||"");
    CLAIMS[cl-1].setAttribute("H",nodedoc.getAttribute("H")||"");
    CLAIMS[cl-1].setAttribute("val",nodedoc.getAttribute("val")||"");
  }
  //alert("Poped "+pn+" "+DumpClaimDocStrat(cl,pn));
}

//---------------------------------------------------------------------------
// Error and warnings attached to claims 
//---------------------------------------------------------------------------

//
// Warning pending on claim because of equivalence
//

function GetClaimEqWarn(cl) {
  return CLAIMS[cl-1].getAttribute("eqwarn");
}

function SetClaimEqWarn(cl,val) {
  //alert("Set claim Eq Warn from "+GetClaimEqWarn(cl)+" to "+val);

  if(val && !GetClaimEqWarn(cl)) {
    //alert("inc eqw");
    IncClaimsWarnings(cl);
    set_Tainted(cl);
  } 
  if(!val && GetClaimEqWarn(cl)){
    //alert("dec eqw");
    DecClaimsWarnings(cl);
    set_Tainted(cl);
  }

  //if(val) alert(val +" "+  GetClaimsWarnings());
  CLAIMS[cl-1].setAttribute("eqwarn",val||"");
}

//
// Warning pending on claim because of grouping
//

function GetClaimGroupWarn(cl) {
  return CLAIMS[cl-1].getAttribute("grpwarn");
}

function SetClaimGroupWarn(cl,val) {
  //alert("Set claim "+cl+"to "+val);
  //alert("Set claim Grp Warn from "+GetClaimGroupWarn(cl)+" to "+val);
  if(val && !GetClaimGroupWarn(cl)) {
    //alert("inc gw");
    IncClaimsWarnings(cl);
    set_Tainted(cl);
  } 
  if(!val && GetClaimGroupWarn(cl)){
    //alert("dec gw");
    DecClaimsWarnings(cl);
    set_Tainted(cl);
  }
  //if(val) alert(val +" "+ GetClaimsWarnings());
  CLAIMS[cl-1].setAttribute("grpwarn",val||"");
}

//---------------------------------------------------------------------------
// Strategy 
// Strategy S is { X, Y, A, B, C} 
//---------------------------------------------------------------------------

// set strategy for cl equal to min(eq,dep) for doc 

function SetMinStrat(cl,eq,dep,doc) {      
   var eq_cat=GetClaimDocStrat(eq,doc);
   var dep_cat=GetClaimDocStrat(dep,doc);
   //alert(eq_cat+" "+dep_cat);
   if(is_catlessorequal(eq_cat,dep_cat)) { 
       _SetClaimDoc_d(cl,eq_cat,doc);
   } else {
       _SetClaimDoc_d(cl,dep_cat,doc);
   }
}

function GetMinStrat(cl1,cl2,doc) {
  //alert("GetMinCat("+cat1+","+cat2+","+doc+")");
  var cat1=GetClaimDocStrat(cl1,doc);
  var cat2=GetClaimDocStrat(cl2,doc);
     
  if(is_catlessorequal(cat1,cat2)) {
    //alert(cat1+"<"+cat2);
    return cat1; 
   } else {
    //alert(cat1+">="+cat2);
    return cat2;
   }
}

//---------------------------------------------------------------------------

// Check strategy is ok with doc value
//
// Only can set X for doc iff X(dep(cl))==doc
//

function GetClaimDoc_X(cl) {
  return CLAIMS[cl-1].getAttribute("X")||"";
}

function _SetClaimDoc_X(cl,pn) {
  _SetClaimDoc_d(cl,"X",pn);  
}

// 
// claim cl, parent of cl is dep
// X(cl) == PN iff X(dep)== PN or Val(dep,PN)==XN, allows for changing X doc in
// different branches but only through novelty paths
// 

function SetClaimDoc_X(cl,pn) {
  var eqcl=GetClaimEq(cl);
  var dep=GetClaimDep(cl);
  var oldx=GetClaimDoc_X(cl);
  //alert("Set X="+pn+" for claim "+cl);
  if(eqcl) {  // equal claim 
    return XML_CLM.ERR_EQ;
    if(pn !=GetClaimDoc_X(eqcl)){ // cannot set same value as optdoc because of eq 
      if(!IsClaimFullFeatured(cl,pn)) {
	SetClaimEqWarn(cl,"Cannot set X="+pn+" because claim "+cl+" eq to "+eqcl+" and X for "+
		       eqcl+" is "+GetClaimDoc_X(eqcl));      
	return XML_CLM.ERR_EQ;
      }
    }
  }

  if(oldx!=pn) {    
    if(dep_isdependent(dep)) { // dependent claim     
      // cannot set pn as X because dep has different X doc, except for forked XN 
      if(pn && pn !=GetClaimDoc_X(dep)) {
	if(GetClaimDocVal(dep,pn) != "XN"){
	  alert("Bad strategy fork for claim "+cl+": depends on "+dep +" which is "+GetClaimDocVal(dep,pn));
	  return XML_CLM.ERR_DEP;
	} else {
	  SetClaimStratFork(cl,"yes");
	}
      } else {
	SetClaimStratFork(cl,"");
      }
    } 
    
    if(pn && GetClaimDocVal(cl,pn) == "A") { // cannot set because of value conflict
      return XML_CLM.ERR_VAL;
    }
    _SetClaimDoc_X(cl,pn);
  }
  return XML_CLM.ERR_NO;
}


//---------------------------------------------------------------------------

function GetClaimDoc_Y(cl) {
  return CLAIMS[cl-1].getAttribute("Y")||"";
}


function SetClaimDoc_Y(cl,pn) {
  var eqcl=GetClaimEq(cl);
  var dep=GetClaimDep(cl);

  if(eqcl) {  // equal claim
    return XML_CLM.ERR_EQ; 
    if(pn !=GetClaimDoc_Y(eqcl)){ // cannot set same value as optdoc because of eq 
      SetClaimEqWarn(cl,"Cannot set Y="+pn+" because claim "+cl+" eq to "+eqcl+" and Y for "+
		     eqcl+" is "+GetClaimDoc_Y(eqcl));  
      return XML_CLM.ERR_EQ;
    }
  }
  
  if(is_cldependent(cl)) { // dependent claim
    // check value, not strat
    if(pn && (GetClaimDoc_A(dep) ==pn || GetClaimDoc_B(dep)==pn ||
	      GetClaimDocVal(dep,pn)=="A")){ 
      return XML_CLM.ERR_DEP;// cannot set same value as optdoc because of dep 
    }
  } 
  if(!GetClaimDoc_X(cl)) {
    // if (no Y1 (X), chosen, cannot use Y  
    return XML_CLM.ERR_BADY;
  }
  if(pn && GetClaimDocVal(cl,pn) == "A") { // cannot set because of value conflict
    return XML_CLM.ERR_VAL;
  }

  

  // every thing is OK, do it 
  _SetClaimDoc_d(cl,"Y",pn); 
  
  return XML_CLM.ERR_NO;
}

//---------------------------------------------------------------------------

function GetClaimDoc_A(cl) {
  return CLAIMS[cl-1].getAttribute("A")||"";
}

function _SetClaimDoc_Ax(cl,doc,val) {
  var eqcl=GetClaimEq(cl);
  if(claim_isgrpindependent(cl) && eqcl) {  // equal claim 
    if(doc!=GetClaimDoc_A(eqcl)){ // cannot set same value as optdoc because of eq 
      return XML_CLM.ERR_EQ;
    }
  }
  // do not allow X->A if Y 
  if(GetClaimDoc_Y(cl) && GetClaimDoc_X(cl)==doc) {
    // if (no Y1 (X), chosen, cannot use Y  
    return XML_CLM.ERR_BADY;
  }
  _SetClaimDoc_d(cl,val,doc); 
  return XML_CLM.ERR_NO; 
}

function SetClaimDoc_A(cl,pn) {
  _SetClaimDoc_Ax(cl,pn,"A");
}

//---------------------------------------------------------------------------

function GetClaimDoc_B(cl) {
  return CLAIMS[cl-1].getAttribute("B")||"";
}

function _SetClaimDoc_B(cl,pn) {
  _SetClaimDoc_d(cl,"B",pn);
}

function SetClaimDoc_B(cl,doc) {
  _SetClaimDoc_Ax(cl,doc,"B");
}

//---------------------------------------------------------------------------

function GetClaimDoc_C(cl) {
  return CLAIMS[cl-1].getAttribute("B2")||"";
}

function SetClaimDoc_C(cl,pn) {
  _SetClaimDoc_Ax(cl,pn,"B2");
}

//---------------------------------------------------------------------------
// flag indicating if a strategy fork is present

function SetClaimStratFork(cl,val) {
  CLAIMS[cl-1].setAttribute("F",val||"");
}

function GetClaimStratFork(cl,val) {
  return CLAIMS[cl-1].getAttribute("F");
}


//---------------------------------------------------------------------------
// Global claim flag for hint (uses first inventive hint)
//---------------------------------------------------------------------------

function GetClaimHint(cl) {
  return CLAIMS[cl-1].getAttribute("H")||"";
}

function SetClaimHint(cl,newhint) {
  var oldhint=GetClaimHint(cl);
  CLAIMS[cl-1].setAttribute("H",(newhint ||""));
  if((oldhint && !newhint) || (!oldhint && newhint)) {
    //alert("Taint "+cl); 
    set_Tainted(cl);
  }
  // update hints for tf.1.1 if only one tf and no present hint already
  if(GetFeaturesLength(cl)==1 && !is_present_hint(GetPassageHint(cl,1,GetClaimDoc_X(cl)))) {
    SetPassageHint(cl,1,GetClaimDoc_X(cl),newhint);
  }
  //alert(cl+": H <= "+newhint+" = "+GetClaimHint(cl));
  PushClaimDocVal(cl,GetClaimDoc_X(cl),"H",newhint);
}



//---------------------------------------------------------------------------
// Select strategy by category (X,Y, A)
//---------------------------------------------------------------------------

function GetClaimDocCat(cl,cat) {
  return (cat && CLAIMS[cl-1].getAttribute(cat));
}

function SetClaimDocCat(cl,cat,doc) {
  if(cat) eval("SetClaimDoc_"+cat+"("+cl+",\""+doc+"\")");
}

//---------------------------------------------------------------------------


//function GetClaimDoc_d(cl,docid) {

function GetClaimDocStrat(cl,docid) {
  if(docid) {
    if(GetClaimDoc_X(cl) == docid) return "X";
    if(GetClaimDoc_Y(cl) == docid) return "Y";
    if(GetClaimDoc_A(cl) == docid) return "A";
    if(GetClaimDoc_B(cl) == docid) return "B";
    if(GetClaimDoc_C(cl) == docid) return "C";
  }
  return "";
}


function SetClaimDoc_Clear(cl,pn) {
  var eqcl=GetClaimEq(cl);
  
  if(eqcl) {  // equal claim 
    if(GetClaimDocStrat(cl,eqcl)){ // cannot set same value as optdoc because of eq 
      return XML_CLM.ERR_EQ;
    }
  } 
  _SetClaimDoc_d(cl,"",pn);
  return XML_CLM.ERR_NO;
}
      

function _SetClaimDoc_d(cl,newcat,pn) {
  var oldcat=GetClaimDocStrat(cl,pn);
  //alert("_SetClaimDoc_d("+cl+","+newcat+","+pn+") ["+newcat+"] == ["+oldcat+"] ?");
  var oldx=GetClaimDoc_X(cl);
  if(oldcat != newcat) {
    // retrieved strategy
    if(newcat =="X") {   // ? -> X
      if(oldx) {         // X'-> stack
	//alert("Push strategy "+oldx);
	PushClaimDocStrat(cl,oldx);
      }
      if(pn) {          // stack -> X
	// resurrect X
	//alert("Pop strategy "+pn);
	PopClaimDocStrat(cl,pn);
      }
    }  
    if(oldcat) {// delete previous docid value
      CLAIMS[cl-1].setAttribute(oldcat,"");
    }
    if(newcat) { // set new strat value for doc 
      CLAIMS[cl-1].setAttribute(newcat,pn||"");
    }
    //alert("Now X for "+cl+" is "+GetClaimDoc_X(cl));
    if(oldcat=="X" || newcat=="X"){
      update_B_hints(cl,pn);
    }
    if(pn && !GetClaimDocVal(cl,pn)) {     // propagate to val if val not set
      //alert("Set val "+newcat+" for "+cl);
      SetClaimDocVal(cl,pn,claimstrat_toclaimval(newcat));
      //alert(GetClaimDocVal(cl,pn));
    }    
    set_Tainted(cl);
    
    // update current strategy with new value
    PushClaimDocVal(cl,GetClaimDoc_X(cl),claimstrat_tolocalstrat(newcat),pn);    
  }
}
 

// Set doc strategy for claim cl, delete previous values 

function SetClaimDocStrat(cl,xyab,docid) {
  var err="";
  //alert("SetClaimDoc_d("+cl+","+xyab+","+docid+")");
  switch(xyab) {
  case "X":
    err=SetClaimDoc_X(cl,docid);
    break;
  case "Y":
    err= SetClaimDoc_Y(cl,docid);
    break;
  case "A":
  case "B":
  case "C":    
    err= _SetClaimDoc_Ax(cl,docid,xyab);
    break;
  case "H":
    SetClaimHint(cl,docid);
    break;
  default:
    err=SetClaimDoc_Clear(cl,docid);    
  }
  //alert("Error :" + err);
  switch(err) {
  case XML_CLM.ERR_EQ:
    alert("Cannot set "+xyab+"["+cl+"] to "+docid+" because equality");
    break;
  case XML_CLM.ERR_VAL:
    alert("Cannot set "+xyab+"["+cl+"] to "+docid+" because value conflict");
    break;
  case XML_CLM.ERR_BADY:
    alert("Cannot use "+docid+" as Y (Y2) document for claim "+cl+" because of missing X (Y1) document.");
    break;
  case XML_CLM.ERR_DEP:
    alert("Cannot set "+xyab+"["+cl+"] to "+docid+" because dependency conflict");
    break;
  case XML_CLM.ERR_BHINT:
    alert("Cannot set "+xyab+"["+cl+"] to "+docid+" because not X document");
    break;
  }
  return err;
}

function GetClaimDocs(cl) {
  return CLAIMS[cl-1].selectSingleNode("clsdocs");
}

// For TMP documents 
function RenameClaimDocVal(cl,oldid,newid) {
  var clsdocs=GetClaimDocs(cl);
  var nodedoc=clsdocs.selectSingleNode("cldoc [ @docid = \""+oldid+"\"]");
  if(nodedoc) {
    nodedoc.setAttribute("docid",newid);
  }
}

function GrantClaim(cl,pn) {
  _SetClaimDoc_d(cl,"X","");
  _SetClaimDoc_d(cl,"Y","");
  _SetClaimDoc_d(cl,"A",pn);
  _SetClaimDoc_d(cl,"B","");
  _SetClaimDoc_d(cl,"C","");
  _SetClaimDoc_d(cl,"H","");
  SetClaimNovelandInventive(cl);
}
  

function claimdocs_iterator(cl) {
  this._docs=GetClaimDocs(cl);
  this._idx=0;

  if(this._docs) {
    this._docs=this._docs.childNodes;
    this.end = function() {
      return this._idx>=this._docs.length;
    }
  } else {
    this.end = function() {
      return true;
    }
  }
}

claimdocs_iterator.prototype.getPN = function() {
  return this._docs[this._idx].getAttribute("docid");
}
claimdocs_iterator.prototype.getVal = function() {
  //alert( this._docs[this._idx].getAttribute("docval"));
  return this._docs[this._idx].getAttribute("docval");
}
claimdocs_iterator.prototype.setVal = function(val) {
  return this._docs[this._idx].setAttribute("docval",val||"");
}
claimdocs_iterator.prototype.next = function() {
  this._idx++;
}


// iterator on claim interval 
function claim_iterator(cl1,cl2,vers) {
  this._claims=GetClaimSetClaims(vers);
  this._end=(cl2 || this._claims.length);
  this._beg=cl1 ? cl1-1 : 0;  
  this._idx=this._beg;
  this._vers=vers;
}
claim_iterator.prototype.end = function() {return this._idx>= this._end;}
claim_iterator.prototype.next = function() { this._idx++ ;}
claim_iterator.prototype.reset = function() { this._idx=this._beg; return this;}
claim_iterator.prototype.last = function() { return this._end;}
claim_iterator.prototype.seek = function(val) { this._idx=val-1;}

claim_iterator.prototype.getValue = function() { return this._idx+1;}  
claim_iterator.prototype.getDep   = function() { return this._claims[this._idx].getAttribute("dep");}   
claim_iterator.prototype.getGroup = function() { return this._claims[this._idx].getAttribute("G");}   
claim_iterator.prototype.setGroup = function(g) { this._claims[this._idx].setAttribute("G",g||"");}   
claim_iterator.prototype.getEq   = function()  { return this._claims[this._idx].getAttribute("eq");}   
  claim_iterator.prototype.getText = function()  { return GetClaimDescription(this._idx+1,this._vers); }   
claim_iterator.prototype.List = function () {
  var clist= new List();
  for(var n=idx+1; n<=this._end; n++){
      clist.push(n);
  }
  return clist;
}
claim_iterator.prototype.select    = function (f) { 
  var _lout=new List();
  for(var cl=this._beg+1; cl<=this._end; cl++) {
    if(f(cl)) {
      _lout.push(cl);
    }
  }  
  return _lout;
}
claim_iterator.prototype.map    = function (f) { 
  for(var cl=this._beg+1; cl<=this._end; cl++) {
    f(cl);
  }  
}
claim_iterator.prototype.reduce    = function (f) { 
  var tmp;
  for(var cl=this._beg+1; cl<=this._end; cl++) {
    tmp=f(cl,tmp);
  }
  return tmp;
}


// for filling tabidx field 
function tab_iterator(offset) {
  this.EQOFF=GetClaimSetLength()+1;
  this._end= GetClaimSetLength();
  this._idx= offset || 0;   
  this.end = function() {return this._idx>= this._end;}
  this.next = function() { this._idx++ ;}
  this.getDep = function() { return this._idx;}
  this.getEq = function() { return this._idx+this.EQOFF;}  
}


// select claims by query
function query_claim_iterator(query) {
  // if I am eq to someone, cannot be pointed by someone else 
  if(!query) {
    this.end = function() { return true;}
  } else {
    this._nodes=CLAIMSET.selectNodes("claims/claim[ "+query+" ]");
    this._idx=0;
    this.end = function () {
      return this._idx >= this._nodes.length;
    }    
  }
}
    //alert("Found "+this._nodes.length);
query_claim_iterator.prototype.getValue = function () {
  //alert(this._nodes[this._idx].parentNode.nodeName);
  return this._nodes[this._idx].getAttribute("clnum");
}
query_claim_iterator.prototype.getGroup = function () {
  return this._nodes[this._idx].getAttribute("G");
}
query_claim_iterator.prototype.getClarity = function () {
  return this._nodes[this._idx].getAttribute("C");
}
query_claim_iterator.prototype.getDoc_X = function () {
  return this._nodes[this._idx].getAttribute("X");
}
query_claim_iterator.prototype.getDoc_Y = function () {
  return this._nodes[this._idx].getAttribute("Y");
}
query_claim_iterator.prototype.setEq = function (eq) {
  this._nodes[this._idx].setAttribute("eq",eq||"");
}
query_claim_iterator.prototype.getEq = function () {
  return this._nodes[this._idx].getAttribute("eq");
}
query_claim_iterator.prototype.next = function () {
  this._idx++;
}
  

function Eq_claim_iterator(cl) {
  return new query_claim_iterator("@eq=\""+cl+"\"");
}
